﻿using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using AntEater.Runtime.UI;
using AntEater.Runtime;

namespace AntEater.Integration.ToolWindows
{
    /// <summary>
    /// Provides the Target Execution Tool Window.
    /// </summary>
    [Guid(Guids.TargetExecutionToolWindowId)]
    public class TargetExecutionToolWindow : ToolWindowPane
    {
        private ITargetExecutionPresenter _presenter;
        private IAntEaterRuntime _runtime;

        /// <summary>
        /// Initializes a new instance of the <see cref="TargetExecutionToolWindow"/> class.
        /// </summary>
        public TargetExecutionToolWindow()
            : base(null) {

            // Set properties
            this.Caption = Strings.TargetExecutionWindowName;
            this.BitmapResourceID = Ressources.TargetExecutionBitmap;
            this.BitmapIndex = 0;

            // Initialize toolbar
            this.ToolBar = Utilities.CreateCommandId(Commands.TargetExecutionToolbar);
            this.ToolBarLocation = (int)VSTWT_LOCATION.VSTWT_TOP;

            // Get presenter from runtime instance
            _runtime = AntEaterRuntime.Instance;
            _presenter = _runtime.Presenters.GetService(typeof(ITargetExecutionPresenter)) as ITargetExecutionPresenter;
        }

        /// <summary>
        /// Gets the window.
        /// </summary>
        /// <value>The window.</value>
        public override IWin32Window Window {
            get { return (IWin32Window)_presenter.View.Surface; }
        }

        /// <summary>
        /// Called when the tool window were created.
        /// </summary>
        public override void OnToolWindowCreated() {
            base.OnToolWindowCreated();

            // Initialize commands
            this.InitializeCommands();
            
            // Register events
            _runtime.Solution.Changed += new EventHandler<EventArgs>(this.SolutionChanged);
            _presenter.SelectionChanged += new EventHandler<EventArgs>(this.PresenterSelectionChanged);
            _presenter.OpenFile += new EventHandler<BuildFileViewEventArgs>(this.PresenterOpenFile);

            // Refresh view
            _presenter.Refresh();
        }

        /// <summary>
        /// Initializes the commands.
        /// </summary>
        private void InitializeCommands() {
            // add commands
            Utilities.AddCommand(this, new EventHandler(this.ExecuteBuildFile), new EventHandler(this.QueryExecuteBuildFile), Commands.ExecuteBuildFileCommand);
            Utilities.AddCommand(this, new EventHandler(this.AddBuildFile), new EventHandler(this.QueryAddBuildFile), Commands.AddBuildFileCommand);
            Utilities.AddCommand(this, new EventHandler(this.RemoveBuildFile), new EventHandler(this.QueryRemoveBuildFile), Commands.RemoveBuildFileCommand);
            Utilities.AddCommand(this, new EventHandler(this.Refresh), Commands.RefreshCommand);
            Utilities.AddCommand(this, new EventHandler(this.EditExternalBuildProperties), new EventHandler(this.QueryEditExternalBuildProperties), Commands.EditExternalBuildPropertiesCommand);
            Utilities.AddCommand(this, new EventHandler(this.ViewDesignerBuildFile), new EventHandler(this.QueryViewDesignerBuildFile), Commands.DesignerViewBuildFileCommand);
            Utilities.AddCommand(this, new EventHandler(this.ViewCodeBuildFile), new EventHandler(this.QueryViewCodeBuildFile), Commands.CodeViewBuildFileCommand); 
        }

        /// <summary>
        /// Presenters the open file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="AntEater.Runtime.UI.BuildFileViewEventArgs"/> instance containing the event data.</param>
        private void PresenterOpenFile(object sender, BuildFileViewEventArgs e) {
            SolutionManager.GetInstance().OpenFile(e.BuildFilePath, e.View);
        }

        /// <summary>
        /// Solutions the changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SolutionChanged(object sender, EventArgs e) {
            this.QueryExecuteBuildFile(sender, e);
            this.QueryAddBuildFile(sender, e);
            this.QueryRemoveBuildFile(sender, e);
        }

        /// <summary>
        /// Presenters the selection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PresenterSelectionChanged(object sender, EventArgs e) {
            this.QueryExecuteBuildFile(sender, e);
            this.QueryAddBuildFile(sender, e);
            this.QueryRemoveBuildFile(sender, e);
        }

        /// <summary>
        /// Executes the build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ExecuteBuildFile(object sender, EventArgs e) {
            _presenter.ExecuteBuildFile();
        }

        /// <summary>
        /// Adds the build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AddBuildFile(object sender, EventArgs e) {
            _presenter.AddBuildFile();
        }

        /// <summary>
        /// Removes the build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void RemoveBuildFile(object sender, EventArgs e) {
            _presenter.RemoveBuildFile();
        }

        /// <summary>
        /// Refreshes the specified sender.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Refresh(object sender, EventArgs e) {
            SolutionManager.GetInstance().Refresh();
            _presenter.Refresh();
        }

        /// <summary>
        /// Views the designer build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ViewDesignerBuildFile(object sender, EventArgs e) {
            SolutionManager.GetInstance().OpenFile(_presenter.SelectedBuildFile.BuildFilePath, BuildFileViewType.Designer);
        }

        /// <summary>
        /// Views the code build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ViewCodeBuildFile(object sender, EventArgs e) {
            SolutionManager.GetInstance().OpenFile(_presenter.SelectedBuildFile.BuildFilePath, BuildFileViewType.Xml);
        }

        /// <summary>
        /// Edits the external build properties.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void EditExternalBuildProperties(object sender, EventArgs e) {
            _presenter.EditExternalBuildProperties();
        }

        /// <summary>
        /// Queries the execute build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryExecuteBuildFile(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.ExecuteBuildFileCommand).Visible = _presenter.SelectedBuildFile != null;
        }

        /// <summary>
        /// Queries the add build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryAddBuildFile(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.AddBuildFileCommand).Visible = _runtime.Solution.BuildFiles.Count > 0;
        }

        /// <summary>
        /// Queries the remove build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryRemoveBuildFile(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.RemoveBuildFileCommand).Visible = _presenter.SelectedBuildFile != null;
        }

        /// <summary>
        /// Queries the edit external build properties.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryEditExternalBuildProperties(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.EditExternalBuildPropertiesCommand).Visible = _runtime.Solution.IsOpen;
        }


        /// <summary>
        /// Queries the view designer build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryViewDesignerBuildFile(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.DesignerViewBuildFileCommand).Visible = _presenter.SelectedBuildFile != null;
        }

        /// <summary>
        /// Queries the view code build file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void QueryViewCodeBuildFile(object sender, EventArgs e) {
            Utilities.GetCommand(this, Commands.CodeViewBuildFileCommand).Visible = _presenter.SelectedBuildFile != null;
        }
    }
}
